﻿using SimpleMapper;
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Text;

namespace TestApp
{
    class Program
    {
        static void Main(string[] args)
        {
            var stopwatch = Stopwatch.StartNew();

            #region type
            stopwatch.Restart();
            var sourceList = Source.GetList(10000000);
            Console.WriteLine("{0} 创建对象({1}个)耗时", stopwatch.Elapsed, sourceList.Count);

            stopwatch.Restart();
            _ = sourceList.To<Destination>();
            Console.WriteLine("{0} 映射到对象耗时", stopwatch.Elapsed);


            stopwatch.Restart();
            var list = new List<Destination>();
            foreach (var item in sourceList)
            {
                list.Add(new Destination
                {
                    Int32Value = item.Int32Value,
                    CharValue = item.CharValue,
                    DecimalValue = item.DecimalValue,
                    DateTimeValue = item.DateTimeValue,
                    Int32NullValue = item.Int32NullValue,
                    StringValue = item.StringValue
                });
            }
            Console.WriteLine("{0} 手工映身对象耗时", stopwatch.Elapsed);
            #endregion

            Console.WriteLine();
            
            #region data
            stopwatch.Restart();
            var table = TestClass.GetTestSource(1000000);
            Console.WriteLine("{0} 创建表格({1}行)耗时：", stopwatch.Elapsed, table.Rows.Count);

            stopwatch.Restart();
            _ = table.To<TestClass>();
            Console.WriteLine("{0} 映射对象耗时", stopwatch.Elapsed);

            stopwatch.Restart();
            foreach (DataRow row in table.Rows)
            {
                var item = new TestClass
                {
                    StringValue = row["StringValue"].ToString(),
                    IntValue = row.Field<int>("IntValue"),
                    //IntNullableValue = row.Field<int>("IntNullableValue"),
                    EnumValueXXX = (TextEnum)Enum.Parse(typeof(TextEnum), row["EnumValue"].ToString()),
                    EnumNullableValue = (TextEnum)Enum.Parse(typeof(TextEnum), row["EnumNullableValue"].ToString()),
                    DateTimeValue = row.Field<DateTime>("DateTimeValue"),
                    //DateTimeNullableValue = row["DateTImeNullableValue"] == DBNull.Value ? (DateTime?)null : row.Field<DateTime>("DateTimeValue")
                };
                if (row["IntNullableValue"] != DBNull.Value) item.IntNullableValue = int.Parse(row["IntNullableValue"].ToString());
                if (row["DateTimeNullableValue"] != DBNull.Value) item.DateTimeNullableValue = row.Field<DateTime>("DateTimeNullableValue");
            }
            Console.WriteLine("{0} 手动映射耗时", stopwatch.Elapsed);

            var reader = table.CreateDataReader();
            stopwatch.Restart();
            _ = reader.To<TestClass>();
            Console.WriteLine("{0} 读取器映射耗时", stopwatch.Elapsed);
            #endregion

            Console.ReadKey();
        }
    }


    #region Test
    public class TestClass
    {
        public string StringValue { set; get; }
        public int IntValue { set; get; }
        public int? IntNullableValue { set; get; }
        [MappingName(Name = "EnumValue")]
        public TextEnum EnumValueXXX { set; get; }
        public TextEnum? EnumNullableValue { set; get; }
        public DateTime DateTimeValue { set; get; }
        public DateTime? DateTimeNullableValue { set; get; }
        public List<char> CharList { set; get; }

        public static DataTable GetTestSource(int count = 10)
        {
            var table = new DataTable("TestTable");
            table.Columns.Add("stringValue", typeof(string));
            table.Columns.Add("intValue", typeof(int));
            table.Columns.Add("intNullableValue", typeof(string));
            table.Columns.Add("enumValue", typeof(int));
            table.Columns.Add("enumNullableValue", typeof(string));
            table.Columns.Add("dateTimeValue", typeof(DateTime));
            table.Columns.Add("DateTimeNullableValue", typeof(string));
            for (var i = 0; i < count; i++)
            {
                var row = table.NewRow();
                row["stringValue"] = $"string.{i}";
                row["intValue"] = i;
                row["intNullableValue"] = i.ToString();
                row["enumValue"] = i % 3;
                row["enumNullableValue"] = $"Test{i % 3 + 1}";
                row["dateTimeValue"] = DateTime.MinValue.AddYears(i % 9000);
                row["dateTImeNullableValue"] = DBNull.Value;
                table.Rows.Add(row);
            }
            return table;
        }
    }
    public enum TextEnum
    {
        Test1,
        Test2,
        Test3
    }
    public class Source
    {
        public int Int32Value { set; get; }
        public int? Int32NullValue { set; get; }
        public char CharValue { set; get; }
        public decimal DecimalValue { set; get; }
        public DateTime DateTimeValue { set; get; }
        public string StringValue { set; get; }

        public static List<Source> GetList(int count = 1)
        {
            var result = new List<Source>();
            for (var i = 0; i < count; i++)
            {
                var item = new Source
                {
                    Int32Value = i,
                    CharValue = 'Y',
                    DecimalValue = i,
                    DateTimeValue = DateTime.Now,
                };
                if (i % 2 == 0)
                {
                    item.Int32NullValue = i;
                    item.StringValue = i.ToString();
                }
                result.Add(item);
            }
            return result;
        }
    }

    public class Destination
    {
        public int Int32Value { set; get; }
        public int? Int32NullValue { set; get; }
        public char CharValue { set; get; }
        public decimal DecimalValue { set; get; }
        public DateTime DateTimeValue { set; get; }
        public string StringValue { set; get; }
    }
    #endregion
}
